package org.wmq.taskschedule.algorithm;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

/**
 * Sobel边缘检测算法执行器
 * 实现AlgorithmExecutor接口，用于对图像进行Sobel边缘检测
 */
public class SobelEdgeDetector implements AlgorithmExecutor {

    private int ddepth; // 输出图像的深度
    private int dx; // x方向导数的阶数
    private int dy; // y方向导数的阶数
    private int ksize; // Sobel核的大小
    private double scale; // 计算导数时的比例因子
    private double delta; // 可选的delta值，加到结果中
    private String description; // 算法描述

    /**
     * 默认构造函数，使用默认参数
     */
    public SobelEdgeDetector() {
        this.ddepth = -1; // 使用与输入图像相同的深度
        this.dx = 1;
        this.dy = 1;
        this.ksize = 3;
        this.scale = 1;
        this.delta = 0;
        this.description = "Sobel边缘检测算法 - 检测图像边缘";
    }

    /**
     * 构造函数，允许自定义参数
     * 
     * @param dx x方向导数的阶数
     * @param dy y方向导数的阶数
     * @param ksize Sobel核的大小
     */
    public SobelEdgeDetector(int dx, int dy, int ksize) {
        if (ksize % 2 == 0 || ksize <= 0) {
            throw new IllegalArgumentException("核大小必须是正数且为奇数");
        }
        this.ddepth = -1;
        this.dx = dx;
        this.dy = dy;
        this.ksize = ksize;
        this.scale = 1;
        this.delta = 0;
        this.description = "Sobel边缘检测算法 - 检测图像边缘";
    }

    /**
     * 构造函数，允许自定义所有参数
     * 
     * @param ddepth 输出图像的深度
     * @param dx x方向导数的阶数
     * @param dy y方向导数的阶数
     * @param ksize Sobel核的大小
     * @param scale 计算导数时的比例因子
     * @param delta 可选的delta值，加到结果中
     * @param description 算法描述
     */
    public SobelEdgeDetector(int ddepth, int dx, int dy, int ksize, double scale, double delta, String description) {
        if (ksize % 2 == 0 || ksize <= 0) {
            throw new IllegalArgumentException("核大小必须是正数且为奇数");
        }
        this.ddepth = ddepth;
        this.dx = dx;
        this.dy = dy;
        this.ksize = ksize;
        this.scale = scale;
        this.delta = delta;
        this.description = description;
    }

    @Override
    public Mat execute(Mat input) {
        if (input == null || input.empty()) {
            throw new IllegalArgumentException("输入图像不能为空");
        }

        // 创建输出图像
        Mat output = new Mat();

        // 如果输入不是灰度图像，先转换为灰度
        Mat grayImage = input.clone();
        if (input.channels() > 1) {
            Imgproc.cvtColor(input, grayImage, Imgproc.COLOR_BGR2GRAY);
        }

        // 应用Sobel边缘检测算法
        Imgproc.Sobel(grayImage, output, ddepth, dx, dy, ksize, scale, delta);

        // 转换为8位图像以便显示
        Mat absOutput = new Mat();
        output.convertTo(absOutput, CvType.CV_8U, 1.0, 0.0);

        // 释放中间资源
        if (!grayImage.equals(input)) {
            grayImage.release();
        }
        output.release();

        return absOutput;
    }

    // Getters and setters
    public int getDdepth() {
        return ddepth;
    }

    public void setDdepth(int ddepth) {
        this.ddepth = ddepth;
    }

    public int getDx() {
        return dx;
    }

    public void setDx(int dx) {
        this.dx = dx;
    }

    public int getDy() {
        return dy;
    }

    public void setDy(int dy) {
        this.dy = dy;
    }

    public int getKsize() {
        return ksize;
    }

    public void setKsize(int ksize) {
        if (ksize % 2 == 0 || ksize <= 0) {
            throw new IllegalArgumentException("核大小必须是正数且为奇数");
        }
        this.ksize = ksize;
    }

    public double getScale() {
        return scale;
    }

    public void setScale(double scale) {
        this.scale = scale;
    }

    public double getDelta() {
        return delta;
    }

    public void setDelta(double delta) {
        this.delta = delta;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}